﻿namespace HZY.Framework.Repository.EntityFramework.Interceptor.Audit;

/// <summary>
/// 审计 保存拦截器
/// </summary>
public abstract class AbstractAuditInterceptor : SaveChangesInterceptor
{
    /// <summary>
    /// SavingChanges
    /// </summary>
    /// <param name="eventData"></param>
    /// <param name="result"></param>
    /// <returns></returns>
    public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
    {
        SavingChanges(eventData);
        return base.SavingChanges(eventData, result);
    }

    /// <summary>
    /// SavingChangesAsync
    /// </summary>
    /// <param name="eventData"></param>
    /// <param name="result"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData,
        InterceptionResult<int> result, CancellationToken cancellationToken = default)
    {
        SavingChanges(eventData);
        return base.SavingChangesAsync(eventData, result, cancellationToken);
    }

    /// <summary>
    /// 获取当前用户
    /// </summary>
    /// <returns></returns>
    protected abstract string? GetCurrentUserId();

    /// <summary>
    /// 获取雪花 id
    /// </summary>
    /// <returns></returns>
    protected abstract long GetSnowflakeId();

    /// <summary>
    /// 添加 、 修改 、删除 拦截
    /// </summary>
    /// <param name="eventData"></param>
    protected virtual void SavingChanges(DbContextEventData eventData)
    {
        var entries = eventData.Context?.ChangeTracker.Entries();
        var entityEntries = entries as EntityEntry[] ?? entries?.ToArray();
        if (entityEntries is null)
        {
            return;
        }

        var userId = GetCurrentUserId();

        #region Insert

        var insertEntries = entityEntries
            .Where(w => w is { Entity: IEntity, State: EntityState.Added })
            .Select(item => item)
            .ToList();

        if (insertEntries.Count > 0)
        {
            foreach (var item in insertEntries)
            {
                // 循环审计字段 集合
                foreach (var propertyEntry in item.Properties)
                {
                    if (propertyEntry.Metadata.PropertyInfo is null)
                    {
                        continue;
                    }

                    var propertyInfo = propertyEntry.Metadata.PropertyInfo;

                    // id 处理
                    var tableIdAttribute = TableIdAttribute.GetTableIdAttribute(propertyInfo);
                    if (tableIdAttribute is not null)
                    {
                        tableIdAttribute.Handle(item, propertyEntry, item.State, GetSnowflakeId());
                        continue;
                    }

                    // 处理 时间 和 操作人
                    var tableFieldAttribute = TableFieldAttribute.GetTableFieldAttribute(propertyInfo);
                    tableFieldAttribute?.HandleFill(item, propertyEntry, item.State, userId);
                }
            }
        }

        #endregion

        #region Delete

        var deleteEntries = entityEntries
            .Where(w => w is { Entity: IEntity, State: EntityState.Deleted })
            .Select(item => item)
            .ToList();

        if (deleteEntries.Count > 0)
        {
            foreach (var item in deleteEntries)
            {
                // 处理逻辑删除字段
                var isSoftDeletion = false;
                foreach (var propertyEntry in item.Properties)
                {
                    if (propertyEntry.Metadata.PropertyInfo is null)
                    {
                        continue;
                    }

                    var propertyInfo = propertyEntry.Metadata.PropertyInfo;

                    var logicAttribute = TableLogicAttribute.GetTableLogicAttribute(propertyInfo);
                    if (logicAttribute is not null)
                    {
                        isSoftDeletion = logicAttribute.Handle(item, propertyEntry);
                    }
                }

                // 检查是否设置了 逻辑删除字段，如果没有设置，则不处理
                if (!isSoftDeletion)
                {
                    continue;
                }

                // 处理 时间 和 删除人
                foreach (var propertyEntry in item.Properties)
                {
                    if (propertyEntry.Metadata.PropertyInfo is null)
                    {
                        continue;
                    }

                    var propertyInfo = propertyEntry.Metadata.PropertyInfo;

                    var tableFieldAttribute = TableFieldAttribute.GetTableFieldAttribute(propertyInfo);
                    tableFieldAttribute?.HandleFill(item, propertyEntry, EntityState.Deleted, userId);
                }
            }
        }

        #endregion

        #region Update

        var updateEntries = entityEntries
                .Where(w => w is { Entity: IEntity, State: EntityState.Modified })
                .Select(item => item)
                .ToList()
            ;

        if (updateEntries.Count > 0)
        {
            foreach (var item in updateEntries)
            {
                // 循环审计字段 集合
                foreach (var propertyEntry in item.Properties)
                {
                    if (propertyEntry.Metadata.PropertyInfo is null)
                    {
                        continue;
                    }

                    var propertyInfo = propertyEntry.Metadata.PropertyInfo;

                    // 处理 时间 和 操作人
                    var tableFieldAttribute = TableFieldAttribute.GetTableFieldAttribute(propertyInfo);
                    tableFieldAttribute?.HandleFill(item, propertyEntry, item.State, userId);
                }
            }
        }

        #endregion
    }
}